﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Runtime = Microsoft.SqlServer.Dts.Runtime;
using System.Data.SqlClient;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using SSISFromCode.Helpers;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;

namespace SSISFromCode
{

    internal abstract class FlatFileGenerator : PackageGenerator, IPreConfigureColumns, IRequireSourceConnection
    {

        private FlatFileColumnManager _flatFileColumnManager;

        public override Runtime.Package Generate( Runtime.Application app, ImportOptions options, string destinationConnectionStr, SqlConnection openConnection )
        {
            _flatFileColumnManager = new FlatFileColumnManager( options as IFlatFileColumnOptions );
            return base.Generate( app, options, destinationConnectionStr, openConnection );
        }

        protected override void CreateTable( SqlConnection openConnection )
        {
            base.CreateTable( _flatFileColumnManager.Columns, openConnection );
        }

        protected override void DoActualMapping()
        {
            foreach ( IDTSInputColumn100 inputColumn in _dataDest.InputCollection[0].InputColumnCollection )
            {
                var outputColumn = _dataDest.InputCollection[0].ExternalMetadataColumnCollection[inputColumn.Name];
                outputColumn.Name = inputColumn.Name;
                _dataDestInstance.MapInputColumn( _dataDest.InputCollection[0].ID, inputColumn.ID, outputColumn.ID );
            }
        }

        protected override void ConnectDataFlowSubComponents()
        {
            var path = _pipe.PathCollection.New();
            path.AttachPathAndPropagateNotifications( _dataSource.OutputCollection[0], _dataDest.InputCollection[0] );
        }

        void IPreConfigureColumns.ConfigureColumns()
        {
            _flatFileColumnManager.ExtractColumns();
            _flatFileColumnManager.InitializeMetadata( _connectionSource.InnerObject as IDTSConnectionManagerFlatFile100 );
        }

        /// <summary>
        /// C# trivia: this method *must* be public even though the interface it supports (IRequireSourceConnection) is internal.
        /// The alternative is "internal IRequireSourceConnection.ConfigureSourceConnection."  Not sure which is preferred.
        /// </summary>
        public void ConfigureSourceConnection()
        {
            _connectionSource.Properties[COMMON_PROPERTY_NAMES.NAME].SetValue( _connectionSource, COMPONENT_NAMES.FLAT_FILE_CONNECTION );
            _connectionSource.Properties[COMMON_PROPERTY_NAMES.CONNECTION_STR].SetValue( _connectionSource, _options.Path );
            _connectionSource.Properties[FLAT_FILE_PROPERTY_NAMES.HEADER_ROW_DELIMITER].SetValue( _connectionSource, DELIMITERS.NEWLINE );  // header row must always be on own line
            _connectionSource.Properties[FLAT_FILE_PROPERTY_NAMES.DATA_ROWS_TO_SKIP].SetValue( _connectionSource, 0 );
            _connectionSource.Properties[FLAT_FILE_PROPERTY_NAMES.COLUMN_NAMES_FIRST_ROW].SetValue( _connectionSource, ( (RowBasedFileImportOptions)_options ).ColumnNamesInFirstRow );  // true
            _connectionSource.Properties[FLAT_FILE_PROPERTY_NAMES.ROW_DELIMITER].SetValue( _connectionSource, DELIMITERS.NEWLINE );
        }

        protected override void CreateDataFlowSourceComponent( Runtime.Application app )
        {
            CreateDataFlowSourceComponent( app, OBJECT_CREATION.FLAT_FILE_SOURCE );
        }

        protected override void CreateConnections()
        {
            base.CreateConnections();
            _connectionSource = _package.Connections.Add( OBJECT_CREATION.FLATFILE_CONNECTION );
        }

    }

}
